#include "reader.h"
#include "psam_card.h"
#include "cpu_card.h"
#include "ic_des.h"

/**
  * 功能: 验证PIN
  * 
  *
  * 返回值:
  * 	   
  **/

static s32 cpu_card_verify_pin(reader_op * reader, cpu_data *deal_data)
{
	card_data send;

	if (!reader || !deal_data) {
		debug("cpu_card_verify_pin: para error!!!\n");
		return RET_ERR;
	}

	memset(send.data, 0, READER_BUF_SIZ);
	memcpy(send.data, deal_data->in.deal_pin, 3);
	/* 校验PIN值 */
	send.type	  = READER_CONTACTLESS_CPU;
	send.cla      = 0x00;
	send.cmd.ins  = APDU_VERIFY_PIN;
	send.pa1.p1   = 0x00;
	send.pa2.p2   = 0x00;
	send.len.lc   = 3; 
	send.le	      = 0;   // 指定读取长度
	reader_communication(reader, &send);
	if ((send.sw1 << 8 | send.sw2) != 0x9000) {
		debug("cpu_card_verify_pin: verify pin failed!!! errno:[%02X%02X]\n", \
			send.sw1, send.sw2);
		return (send.sw1 << 8 | send.sw2);
	}
	
	return RET_OK;
}


/**
  * 功能: 消费流程
  * 
  *
  * 返回值:
  * 	   
  **/

static s32 cpu_card_cons_flow(reader_op *reader, cpu_data *deal_data)
{
	card_data send;
	u8 key, crypt;
	u8 challenge[4];
	u8 mac[4];
	s32 ret;
	u32 deal_val;
	u32 discount_val;
	u8 *money;

	if (!reader || !deal_data) {
		debug("cpu_card_cons_flaw: para error!!!\n");
		return RET_ERR;
	}

	deal_data->out.deal_ret = DEAL_RESULT_FAIL;
	/* 1、获取离散因子==卡序列号 */
	ret = reader_get_factor(reader);
	if (ret) {
		return RET_ERR;
	}
	// 电子存折需验证PIN
	if (ED == deal_data->in.deal_type) {
		ret = cpu_card_verify_pin(reader, deal_data);
		if (ret) {
			debug("cpu_card_cons_flaw: verify pin failed!!!\n");
			return RET_ERR;
		}
	}
	
	/* 2、初始化消费交易 */
	deal_val = ((deal_data->in.deal_val[0] << 24) | \
		(deal_data->in.deal_val[1] << 16) | \
		(deal_data->in.deal_val[2] << 8) | \
		(deal_data->in.deal_val[3]));
	discount_val = ((deal_data->in.deal_rebate[0] << 24) | \
		(deal_data->in.deal_rebate[1] << 16) | \
		(deal_data->in.deal_rebate[2] << 8) | \
		(deal_data->in.deal_rebate[3]));
	if (deal_val < discount_val) {
		deal_data->out.deal_ret = DEAL_RESULT_FAIL;
		return RET_ERR;
	}
	deal_val -= discount_val;
	money = (u8 *)&deal_val;
	memset(send.data, 0, READER_BUF_SIZ);
	send.type	  = READER_CONTACTLESS_CPU;
	send.cla      = 0x80;
	send.cmd.ins  = APDU_INITIALIZE_FOR_PURCHASE;
	send.pa1.p1   = 0x01; // 消费
	send.pa2.p2   = deal_data->in.deal_type;
	send.len.lc   = 11; 
	send.le	      = 15;   // 指定读取长度
	send.data[0]  = 0x01; // 密钥索引号
	send.data[1]  = money[3]; // 高位在前
	send.data[2]  = money[2];
	send.data[3]  = money[1];
	send.data[4]  = money[0];
	send.data[5]  = reader->terminal[0]; 
	send.data[6]  = reader->terminal[1]; 
	send.data[7]  = reader->terminal[2]; 
	send.data[8]  = reader->terminal[3]; 
	send.data[9]  = reader->terminal[4]; 
	send.data[10] = reader->terminal[5]; 
	ret = reader_communication(reader, &send);
	if ((send.sw1 << 8 | send.sw2) != 0x9000) {
		debug("cpu_card_cons_flaw: init cons failed!!! errno:[%02X%02X]\n", \
			send.sw1, send.sw2);
		return (send.sw1 << 8 | send.sw2);
	}
	// 初始化消费指令、返回报文数据
	deal_data->out.deal_residue[0]    = send.data[0];  // 交易前余额
	deal_data->out.deal_residue[1]    = send.data[1];
	deal_data->out.deal_residue[2]    = send.data[2];
	deal_data->out.deal_residue[3]    = send.data[3];
	deal_data->out.deal_cnt[0]        = send.data[4];  // 消费交易序号
	deal_data->out.deal_cnt[1]        = send.data[5];  // 消费交易序号
	key                               = send.data[9];  // 密钥版本号
	crypt                             = send.data[10]; // 算法标识
	challenge[0]                      = send.data[11]; // 4字节伪随机数
	challenge[1]                      = send.data[12];
	challenge[2]                      = send.data[13];
	challenge[3]                      = send.data[14];

	/* 3、获取MAC1值 */
	// PSAM mac1 计算指令
	memset(send.data, 0, READER_BUF_SIZ);
	send.type	  = READER_CONTACT_SAM1;
	send.cla      = 0x80;
	send.cmd.ins  = APDU_INIT_SAM_FOR_PURCHASE;
	send.pa1.p1   = 0x00;         // 0:标准MAC1命令，1:扩展MAC1命令
	send.pa2.p2   = 0x00; 
	send.len.lc   = 28; 
	send.le	      = 0x00;         // 指定读取长度
	send.data[0]  = challenge[0]; 
	send.data[1]  = challenge[1];
	send.data[2]  = challenge[2];
	send.data[3]  = challenge[3];
	send.data[4]  = deal_data->out.deal_cnt[0];
	send.data[5]  = deal_data->out.deal_cnt[1]; 
	send.data[6]  = money[3]; 
	send.data[7]  = money[2]; 
	send.data[8]  = money[1]; 
	send.data[9]  = money[0]; 
	send.data[10] = (deal_data->in.deal_type == EP)?0x06:0x05; // 0x06=钱包消费，0x05=存折消费
	send.data[11]  = deal_data->in.deal_time[0];
	send.data[12]  = deal_data->in.deal_time[1];
	send.data[13]  = deal_data->in.deal_time[2];
	send.data[14]  = deal_data->in.deal_time[3];
	send.data[15]  = deal_data->in.deal_time[4]; 
	send.data[16]  = deal_data->in.deal_time[5]; 
	send.data[17]  = deal_data->in.deal_time[6]; 
	send.data[18]  = key; 
	send.data[19]  = crypt; 
	send.data[20]  = reader->card_num[0]; 
	send.data[21]  = reader->card_num[1]; 
	send.data[22]  = reader->card_num[2]; 
	send.data[23]  = reader->card_num[3]; 
	send.data[24]  = reader->card_num[4]; 
	send.data[25]  = reader->card_num[5]; 
	send.data[26]  = reader->card_num[6]; 
	send.data[27]  = reader->card_num[7]; 
	ret = reader_communication(reader, &send);
	if ((send.sw1 == 0x61)) {		
		ret = psam_apdu_get_response(reader, &send, send.sw2);
		if (ret) {
			debug("cpu_card_cons_flaw: get response failed!!!\n");
			return RET_ERR;
		}
	}
	// MAC1计算指令、返回报文
	deal_data->out.deal_index[0] = send.data[0]; // 终端交易序号
	deal_data->out.deal_index[1] = send.data[1];
	deal_data->out.deal_index[2] = send.data[2];
	deal_data->out.deal_index[3] = send.data[3];
	mac[0] = send.data[4]; // MAC1值
	mac[1] = send.data[5];
	mac[2] = send.data[6];
	mac[3] = send.data[7];
	
	/* 4、消费指令 */
	memset(send.data, 0, READER_BUF_SIZ);
	send.type	  = READER_CONTACTLESS_CPU;
	send.cla      = 0x80;
	send.cmd.ins  = APDU_DEBIT_FOR_PURCHASE;
	send.pa1.p1   = 0x01; 
	send.pa2.p2   = 0x00; 
	send.len.lc   = 15; 
	send.le	      = 0x08;   // 指定读取长度
	send.data[0]  = deal_data->out.deal_index[0]; 
	send.data[1]  = deal_data->out.deal_index[1];
	send.data[2]  = deal_data->out.deal_index[2];
	send.data[3]  = deal_data->out.deal_index[3];
	send.data[4]  = deal_data->in.deal_time[0];
	send.data[5]  = deal_data->in.deal_time[1]; 
	send.data[6]  = deal_data->in.deal_time[2]; 
	send.data[7]  = deal_data->in.deal_time[3]; 
	send.data[8]  = deal_data->in.deal_time[4]; 
	send.data[9]  = deal_data->in.deal_time[5]; 
	send.data[10] = deal_data->in.deal_time[6]; 
	send.data[11]  = mac[0];
	send.data[12]  = mac[1];
	send.data[13]  = mac[2];
	send.data[14]  = mac[3];
	ret = reader_communication(reader, &send);
	if ((send.sw1 << 8 | send.sw2) != 0x9000) {
		debug("cpu_card_cons_flaw: cons cmd failed!!! errno:[%02X%02X]\n", \
			send.sw1, send.sw2);
		return (send.sw1 << 8 | send.sw2);
	}
	// 返回报文 tac 和 mac2
	deal_data->out.deal_tac[0] = send.data[0];
	deal_data->out.deal_tac[1] = send.data[1];
	deal_data->out.deal_tac[2] = send.data[2];
	deal_data->out.deal_tac[3] = send.data[3];
	mac[0] = send.data[4];
	mac[1] = send.data[5];
	mac[2] = send.data[6];
	mac[3] = send.data[7];

	/* 5、PSAM MAC2校验 */
	memset(send.data, 0, READER_BUF_SIZ);
	send.type	  = READER_CONTACT_SAM1;
	send.cla      = 0x80;
	send.cmd.ins  = APDU_CREDIT_SAM_FOR_PURCHASE;
	send.pa1.p1   = 0x00; 
	send.pa2.p2   = 0x00; 
	send.len.lc   = 0x04; 
	send.le	      = 0x00;   // 指定读取长度
	send.data[0]  = mac[0]; 
	send.data[1]  = mac[1];
	send.data[2]  = mac[2];
	send.data[3]  = mac[3];

	ret = reader_communication(reader, &send); 
	if ((send.sw1 << 8 | send.sw2) != 0x9000) {
		debug("cpu_card_cons_flaw: check Mac2 failed!!! errno:[%02X%02X]\n", \
			send.sw1, send.sw2);
		deal_data->out.deal_ret = DEAL_RESULT_ABNORMAL;
		return (send.sw1 << 8 | send.sw2);
	}	

	if (DEBUG_APP_WALL > __DEBUG_APP_O0__) {
		debug("DEBGU_info: cpu card deal done\n");
	}

	deal_data->out.deal_ret = DEAL_RESULT_NORMAL;
	return (0x9000);
}


/**
  * 功能: 圈存流程
  * 
  *
  * 返回值:
  * 	   
  **/

static s32 cpu_card_load_flow(reader_op *reader, cpu_data *deal_data)
{
	card_data send;
	u8 key, crypt;
	u8 challenge[4];
	u8 mac[4];
	u8 smac[4];
	u8 *money;
	s32 ret;
	u32 deal_val = 0;
	u32 discount_val = 0;
	u8 i = 0;

	if (!reader || !deal_data) {
		debug("cpu_card_load_flaw: para error!!!\n");
		return RET_ERR;
	}

	deal_data->out.deal_ret = DEAL_RESULT_FAIL;
	/* 1、验证PIN */
	ret = cpu_card_verify_pin(reader, deal_data);
	if (ret) {
		debug("cpu_card_cons_flaw: verify pin failed!!!\n");
		return RET_ERR;
	}
	/* 获取离散因子==卡序列号 */
	ret = reader_get_factor(reader);
	if (ret) {
		return RET_ERR;
	}

	/* 2、初始化圈存命令 */
	deal_val = ((deal_data->in.deal_val[0] << 24) | \
		(deal_data->in.deal_val[1] << 16) | \
		(deal_data->in.deal_val[2] << 8) | \
		(deal_data->in.deal_val[3]));
	discount_val = ((deal_data->in.deal_rebate[0] << 24) | \
		(deal_data->in.deal_rebate[1] << 16) | \
		(deal_data->in.deal_rebate[2] << 8) | \
		(deal_data->in.deal_rebate[3]));
	deal_val += discount_val;
	money = (u8 *)&deal_val;
	memset(send.data, 0, READER_BUF_SIZ);
	send.type	  = READER_CONTACTLESS_CPU;
	send.cla      = 0x80;
	send.cmd.ins  = APDU_INITIALIZE_FOR_PURCHASE;
	send.pa1.p1   = 0x00; // 圈存
	send.pa2.p2   = deal_data->in.deal_type; // EP（电子钱包）ED（电子存折）
	send.len.lc   = 11; 
	send.le	      = 16;   // 指定读取长度
	send.data[0]  = 0x01; // 密钥索引号
	send.data[1]  = money[3]; // 高位在前
	send.data[2]  = money[2];
	send.data[3]  = money[1];
	send.data[4]  = money[0];
	send.data[5]  = reader->terminal[0]; 
	send.data[6]  = reader->terminal[1]; 
	send.data[7]  = reader->terminal[2]; 
	send.data[8]  = reader->terminal[3]; 
	send.data[9]  = reader->terminal[4]; 
	send.data[10] = reader->terminal[5]; 
	ret = reader_communication(reader, &send);
	if ((send.sw1 << 8 | send.sw2) != 0x9000) {
		debug("cpu_card_cons_flaw: init load failed!!! errno:[%02X%02X]\n", \
			send.sw1, send.sw2);
		return (send.sw1 << 8 | send.sw2);
	}
	// 返回报文数据
	deal_data->out.deal_residue[0] = send.data[0];  // 余额
	deal_data->out.deal_residue[1] = send.data[1];
	deal_data->out.deal_residue[2] = send.data[2];
	deal_data->out.deal_residue[3] = send.data[3];
	deal_data->out.deal_cnt[0]     = send.data[4];  // 交易序号
	deal_data->out.deal_cnt[1]     = send.data[5];
	key                            = send.data[6];  // 密钥版本号
	crypt                          = send.data[7];  // 算法标识
	challenge[0]                   = send.data[8]; 	// 4字节伪随机数
	challenge[1]                   = send.data[9];
	challenge[2]                   = send.data[10];
	challenge[3]                   = send.data[11];
	mac[0]	    		           = send.data[12];	// MAC1
	mac[1]						   = send.data[13];	
	mac[2]					       = send.data[14];	
	mac[3]					       = send.data[15];

	/* 3、 计算MAC1/MAC2 */
	// 获取圈存过程密钥 伪随机数||交易序号||8000
	reader->key_data[0] = challenge[0];
	reader->key_data[1] = challenge[1];
	reader->key_data[2] = challenge[2];
	reader->key_data[3] = challenge[3];
	reader->key_data[4] = deal_data->out.deal_cnt[0];
	reader->key_data[5] = deal_data->out.deal_cnt[1];
	reader->key_data[6] = 0x80;
	reader->key_data[7] = 0x00;
	reader->key_len = 8;
	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("sesk input data: %02X%02X%02X%02X%02X%02X%02X%02X\n", \
		reader->key_data[0], reader->key_data[1], reader->key_data[2], \
		reader->key_data[3], reader->key_data[4], reader->key_data[5], \
		reader->key_data[6], reader->key_data[7]);
	}
	ret = psam_card_get_key(reader, CTCC_YJD_KEY_FLAG, CTCC_YJD_KEY_ID_LOAD); // 获取过程密钥
	if (ret) {
		debug("cpu_card_load_flow: get key failed!!!\n");
		return RET_ERR;
	}
	// 计算MAC1值 过程密钥加密 
	// 交易前金额||交易金额||交易类型标识||终端机编号 MAC1输入数据 
	memset(send.data, 0, READER_BUF_SIZ);
	send.data[0]  = deal_data->out.deal_residue[0]; // 余额
	send.data[1]  = deal_data->out.deal_residue[1];
	send.data[2]  = deal_data->out.deal_residue[2];
	send.data[3]  = deal_data->out.deal_residue[3];
	send.data[4]  = money[3]; // 交易金额
	send.data[5]  = money[2];
	send.data[6]  = money[1];
	send.data[7]  = money[0];
	send.data[8]  = deal_data->in.deal_type; // 交易标识
	send.data[9]  = reader->terminal[0]; 
	send.data[10] = reader->terminal[1]; 
	send.data[11] = reader->terminal[2]; 
	send.data[12] = reader->terminal[3]; 
	send.data[13] = reader->terminal[4]; 
	send.data[14] = reader->terminal[5];
	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mac1 input data: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", \
		send.data[0], send.data[1], send.data[2], send.data[3], \
		send.data[4], send.data[5], send.data[6], send.data[7], \
		send.data[8], send.data[9], send.data[10], send.data[11], \
		send.data[12], send.data[13], send.data[14]);
	}
	cel_mac(reader->key_data, send.data, 15, smac); 
	// 验证MAC1
	if (memcmp(smac, mac, 4)) {
		debug("cpu_card_load_flow: check mac1 error!!!\n");
		debug("smac: %02x-%02x-%02x-%02x\n", smac[0], smac[1], smac[2], smac[3]);
		debug("mac: %02x-%02x-%02x-%02x\n", mac[0], mac[1], mac[2], mac[3]);
		return RET_ERR;
	}
	// 计算MAC2
	memset(send.data, 0, READER_BUF_SIZ);
	send.data[0]  = money[3]; // 交易金额
	send.data[1]  = money[2];
	send.data[2]  = money[1];
	send.data[3]  = money[0];
	send.data[4]  = deal_data->in.deal_type; // 交易标识
	send.data[5]  = reader->terminal[0]; 
	send.data[6]  = reader->terminal[1]; 
	send.data[7]  = reader->terminal[2]; 
	send.data[8]  = reader->terminal[3]; 
	send.data[9]  = reader->terminal[4]; 
	send.data[10] = reader->terminal[5];
	send.data[11] = deal_data->in.deal_time[0]; 
	send.data[12] = deal_data->in.deal_time[1]; 
	send.data[13] = deal_data->in.deal_time[2];  
	send.data[14] = deal_data->in.deal_time[3]; 
	send.data[15] = deal_data->in.deal_time[4]; 
	send.data[16] = deal_data->in.deal_time[5];  
	send.data[17] = deal_data->in.deal_time[6]; 
	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("mac2 input data: ");
		for (i=0; i<18; i++) {
			debug("%02X", send.data[i]);
		}
		debug("\n");
	}
	cel_mac(reader->key_data, send.data, 18, smac); 

	/* 圈存 */
	send.type	  = READER_CONTACTLESS_CPU;
	send.cla      = 0x80;
	send.cmd.ins  = APDU_CREDIT_FOR_LOAD;
	send.pa1.p1   = 0x00; 
	send.pa2.p2   = 0x00; 
	send.len.lc   = 11; 
	send.le	      = 0x04;   // 指定读取长度
	send.data[0]  = deal_data->in.deal_time[0];
	send.data[1]  = deal_data->in.deal_time[1]; 
	send.data[2]  = deal_data->in.deal_time[2]; 
	send.data[3]  = deal_data->in.deal_time[3]; 
	send.data[4]  = deal_data->in.deal_time[4]; 
	send.data[5]  = deal_data->in.deal_time[5]; 
	send.data[6]  = deal_data->in.deal_time[6]; 
	send.data[7]  = smac[0];
	send.data[8]  = smac[1];
	send.data[9]  = smac[2];
	send.data[10] = smac[3];
	ret = reader_communication(reader, &send);
	if ((send.sw1 << 8 | send.sw2) != 0x9000) {
		debug("cpu_card_load_flow: load failed!!! errno:[%02X%02X]\n", \
			send.sw1, send.sw2);
		return (send.sw1 << 8 | send.sw2);
	}
	// 返回报文 tac
	deal_data->out.deal_tac[0] = send.data[0];
	deal_data->out.deal_tac[1] = send.data[1];
	deal_data->out.deal_tac[2] = send.data[2];
	deal_data->out.deal_tac[3] = send.data[3];

	if (DEBUG_APP_WALL > __DEBUG_APP_O0__) {
		debug("DEBGU_info: cpu card load done\n");
	}
	
	deal_data->out.deal_ret = DEAL_RESULT_NORMAL;
	return (0x9000);
}


/**
  * 功能: CPU卡进入应用目录
  * 
  *
  * 返回值:
  * 	   
  **/

static s32 cpu_card_select_file(reader_op *reader)
{
	card_data send;

	if (!reader) {
		debug("cpu_card_select_file: pare error!!!\n");
		return RET_ERR;
	}
	// 进入支付系统环境
	memset(send.data, 0, READER_BUF_SIZ);
	strncpy((s8 *)send.data, CPU_CARD_FILE_NAME, strlen(CPU_CARD_FILE_NAME));
	/* 按文件名选择应用文件 */
	send.type    = READER_CONTACTLESS_CPU;
	send.cla     = 0x00;
	send.cmd.ins = APDU_SELECT_FILE;
	send.pa1.p1  = 0x04;
	send.pa2.p2  = 0x00;
	send.len.lc  = strlen((s8 *)send.data);
	send.le      = 0;
	reader_communication(reader, &send);
	if ((send.sw1 << 8 | send.sw2) != 0x9000) {
		debug("select cpu %s file failed\n", CPU_CARD_FILE_NAME);
		return RET_ERR;
	}

	// 进入子目录
	memset(send.data, 0, READER_BUF_SIZ);
	strncpy((s8 *)send.data, CPU_APP_PATH, strlen(CPU_APP_PATH));
	send.type    = READER_CONTACTLESS_CPU;
	send.cla     = 0x00;
	send.cmd.ins = APDU_SELECT_FILE;
	send.pa1.p1  = 0x00;
	send.pa2.p2  = 0x00;
	send.len.lc  = strlen((s8 *)send.data);
	send.le      = 0;
	reader_communication(reader, &send);
	if ((send.sw1 << 8 | send.sw2) != 0x9000) {
		debug("select DF10 file failed\n");
		return RET_ERR;
	}

	if (DEBUG_APP_WALL > __DEBUG_APP_O1__) {
		debug("DEBGU_info: cpu card select file done\n");
	}

	return RET_OK;
}



/**
  * 功能: CPU卡消费交易
  * 
  *
  * 返回值:
  * 	   
  **/

s32 cpu_card_cons(void *op, void *data)
{
	s32 ret = 0;
	reader_op *reader = (reader_op *)op;
	cpu_data *deal_data = (cpu_data *)data;

	if (!op || !data || reader->card_type != NORMAL_CPU_CARD) {
		debug("cpu_card_deal: para error!!!\n");
		return RET_ERR;
	}

	// 选择CPU文件
	ret = cpu_card_select_file(reader);
	if (ret) {
		return RET_ERR;
	}

	// 交易认证过程
	ret = cpu_card_cons_flow(reader, deal_data);
	if (ret != 0x9000) {
		return RET_ERR;
	}


	return RET_OK;
}


/**
  * 功能: CPU卡圈存交易
  * 
  *
  * 返回值:
  * 	   
  **/

s32 cpu_card_load(void *op, void *data)
{
	s32 ret = 0;
	reader_op *reader = (reader_op *)op;
	cpu_data  *deal_data = (cpu_data *)data;

	if (!op || !data || reader->card_type != NORMAL_CPU_CARD) {
		debug("cpu_card_deal: para error!!!\n");
		return RET_ERR;
	}

	// 选择CPU文件
	ret = cpu_card_select_file(reader);
	if (ret) {
		return RET_ERR;
	}
	
	// 交易认证过程
	ret = cpu_card_load_flow(reader, deal_data);
	if (ret != 0x9000) {
		return RET_ERR;
	}

	return RET_OK;
}


#if 0
int cpu_card_inquiry(void *info)
{
	int ret;
	char buf[128];
	card_data send;

	if (!info) {
		debug("cpu_card_inquiry: para error!!!\n");
		return RET_ERR;
	}

	/* 按文件名选择文件 */
	send_send.type    = READER_CONTACTLESS_CPU;
	send_send.CLA     = 0x00;
	send_send.CMD.INS = APDU_SELECT_FILE;
#ifdef __USE_FIXED_AID__
	send_send.PA1.P1  = 0x00;
	send_send.LEN.Lc  = 2;
	send_send.DATA[0] = 0xDF;
	send_send.DATA[1] = 0x10;
#else
	send_send.PA1.P1  = 0x04;
	send_send.LEN.Lc  = 16;
	for(ret=0; ret<16; ret++) {
		send_send.DATA[ret] = server_info.CardAID[ret];
	}
#endif
	debug("select CPU YJT\n");
	reader_transcive(&send_send, &send_send);
#if 0
	if((send_send.SW1!=0x90) || (send_send.SW2!=0x00)) {
		debug("select user card(CPU) YJT app fail\n");
		return -ERR_CARD_OP;
	}
#endif

	/* 读二进制带SFI选择文件 */
	send_send.type    = READER_CONTACTLESS_CPU;
	send_send.CLA     = 0x00;
	send_send.CMD.INS = APDU_READ_BINARY;
	send_send.PA1.P1  = 0x95; /* bit7=1，bit6-bit5=0，bit4-bit0='SFI' */
	send_send.PA2.P2  = 10; /* 指定读取偏移量（相对文件头部）*/
	send_send.LEN.Lc  = 0; 
	send_send.Le      = 18; /* 指定读取长度 */
	reader_transcive(&send_send, &send_send);
	if((send_send.SW1!=0x90) || (send_send.SW2!=0x00)) {
		debug("read CPU SFI-21 fail\n");
		return -ERR_CARD_OP;
	}
	info->asn[0] = send_send.DATA[0];
	info->asn[1] = send_send.DATA[1];
	info->asn[2] = send_send.DATA[2];
	info->asn[3] = send_send.DATA[3];
	info->asn[4] = send_send.DATA[4];
	info->asn[5] = send_send.DATA[5];
	info->asn[6] = send_send.DATA[6];
	info->asn[7] = send_send.DATA[7];
	info->asn[8] = send_send.DATA[8];
	info->asn[9] = send_send.DATA[9];
	info->app_begin = (send_send.DATA[13]<<0)
		| (send_send.DATA[12]<<8)
		| (send_send.DATA[11]<<16)
		| (send_send.DATA[10]<<24);
	info->card_indate = (send_send.DATA[17]<<0)
		| (send_send.DATA[16]<<8)
		| (send_send.DATA[15]<<16)
		| (send_send.DATA[14]<<24);

	send_send.type    = READER_CONTACTLESS_CPU;
	send_send.CLA     = 0x00;
	send_send.CMD.INS = APDU_READ_BINARY;
	send_send.PA1.P1  = 0x96; /* bit7=1，bit6-bit5=0，bit4-bit0='SFI' */
	send_send.PA2.P2  = 2; /* 指定读取偏移量（相对文件头部）*/
	send_send.LEN.Lc  = 0; 
	send_send.Le      = 20; /* 指定读取长度 */
	send_send.DATA    = info->name;
	reader_transcive(&send_send, &send_send);
	if((send_send.SW1!=0x90) || (send_send.SW2!=0x00)) {
		debug("read CPU SFI-22 fail\n");
		return -ERR_CARD_OP;
	}

	send_send.type    = READER_CONTACTLESS_CPU;
	send_send.CLA     = 0x00;
	send_send.CMD.INS = APDU_READ_BINARY;
	send_send.PA1.P1  = 0x96; /* bit7=1，bit6-bit5=0，bit4-bit0='SFI' */
	send_send.PA2.P2  = 88; /* 指定读取偏移量（相对文件头部）*/
	send_send.LEN.Lc  = 0; 
	send_send.Le      = 13; /* 指定读取长度 */
	send_send.DATA    = buf;
	reader_transcive(&send_send, &send_send);
	if((send_send.SW1!=0x90) || (send_send.SW2!=0x00)) {
		debug("read CPU SFI-22 fail\n");
		return -ERR_CARD_OP;
	}
#define __CST_CARD_TYPE__ 0
/* 郑州新开普、江苏鸿程 */
#define __OTHER_CARD_TYPE__ 1
/* 广州亿迅和浙江鸿程 */
#define __YIXUN_CARD_TYPE__ 0

#if __CST_CARD_TYPE__
#warning "use cst card type define[88]" 
	info->card_class = send_send.DATA[88-88];
#elif __OTHER_CARD_TYPE__
#warning "use other card type define[98]" 
	info->card_class = send_send.DATA[98-88];
#elif __YIXUN_CARD_TYPE__
#warning "use yixun card type define[100]" 
	info->card_class = send_send.DATA[100-88]; /* 广州亿迅 */
#else
#error "please define a card type byte" 
#endif
#undef __CST_CARD_TYPE__
#undef __OTHER_CARD_TYPE__
#undef __YIXUN_CARD_TYPE__
	info->card_func = send_send.DATA[97-88];

	send_send.type    = READER_CONTACTLESS_CPU;
	send_send.CLA     = 0x00;
	send_send.CMD.INS = APDU_READ_BINARY;
	send_send.PA1.P1  = 0x99; /* bit7=1，bit6-bit5=0，bit4-bit0='SFI' */
	send_send.PA2.P2  = 0; /* 指定读取偏移量（相对文件头部）*/
	send_send.LEN.Lc  = 0; 
	send_send.Le      = 54; /* 指定读取长度 */
	send_send.DATA    = info->card_private_info;
	reader_transcive(&send_send, &send_send);
	if((send_send.SW1!=0x90) || (send_send.SW2!=0x00)) {
		debug("read CPU SFI-25 fail\n");
		return -ERR_CARD_OP;
	}

	info->card_status = info->card_private_info[0];
	info->terminal_no[0] = info->card_private_info[1];
	info->terminal_no[1] = info->card_private_info[2];
	info->terminal_no[2] = info->card_private_info[3];
	info->terminal_no[3] = info->card_private_info[4];
	info->terminal_no[4] = info->card_private_info[5];
	info->terminal_no[5] = info->card_private_info[6];
	info->consume_indate = (info->card_private_info[7]<<24)
		| (info->card_private_info[8]<<16)
		| (info->card_private_info[9]<<8)
		| (info->card_private_info[10]<<0);
	info->limit_v_per_meal = (info->card_private_info[15]<<8)
		| (info->card_private_info[16]<<0);
	info->limit_v_per_deal = (info->card_private_info[17]<<8)
		| (info->card_private_info[18]<<0);
	info->limit_v_per_day = (info->card_private_info[19]<<8)
		| (info->card_private_info[20]<<0);
	info->meal_sum = (info->card_private_info[32]<<24)
		| (info->card_private_info[33]<<16)
		| (info->card_private_info[34]<<8)
		| (info->card_private_info[35]<<0);
	info->day_sum = (info->card_private_info[36]<<24)
		| (info->card_private_info[37]<<16)
		| (info->card_private_info[38]<<8)
		| (info->card_private_info[39]<<0);
	info->last_use_date = (info->card_private_info[40]<<8)
		| (info->card_private_info[41]<<0);
	info->last_meal_type = info->card_private_info[42];
	info->last_meal_cnt = info->card_private_info[43];
	info->last_day_cnt = info->card_private_info[44];
	info->ed_zero_date = (info->card_private_info[45]<<24)
		| (info->card_private_info[46]<<16)
		| (info->card_private_info[47]<<8)
		| (info->card_private_info[48]<<0);
	info->passwd_mac = (info->card_private_info[21]<<24)
		| (info->card_private_info[22]<<16)
		| (info->card_private_info[23]<<8)
		| (info->card_private_info[24]<<0);
	info->passwd_ver = (info->card_private_info[25]<<24)
		| (info->card_private_info[26]<<16)
		| (info->card_private_info[27]<<8)
		| (info->card_private_info[28]<<0);

	/* 读取电子钱包电子存折的余额 */
	send_send.type    = READER_CONTACTLESS_CPU;
	send_send.CLA     = 0x80;
	send_send.CMD.INS = APDU_GET_BALANCE;
	send_send.PA1.P1  = 0x00;
	send_send.PA2.P2  = 0x02; /* 0x01=ED（电子存折）, 0x02=EP（电子钱包）*/
	send_send.LEN.Lc  = 0; 
	send_send.Le      = 4; /* 指定读取长度 */
	send_send.DATA    = buf;
	reader_transcive(&send_send, &send_send);
	if((send_send.SW1!=0x90) || (send_send.SW2!=0x00)) {
		debug("get ep balance fail\n");
		return -ERR_CARD_OP;
	}
	info->ep_balance = (send_send.DATA[0]<<24)
			| (send_send.DATA[1]<<16)
			| (send_send.DATA[2]<<8)
			| (send_send.DATA[3]<<0);
	/* 操作电子存折前验证PIN */
	send_send.type    = READER_CONTACTLESS_CPU;
	send_send.CLA     = 0x00;
	send_send.CMD.INS = APDU_VERIFY_PIN;
	send_send.PA1.P1  = 0x00;
	send_send.PA2.P2  = 0x00;
	send_send.LEN.Lc  = 3; 
	send_send.Le      = 0; /* 指定读取长度 */
	send_send.DATA[0] = 0;
	send_send.DATA[1] = 0;
	send_send.DATA[2] = 0;
	reader_transcive(&send_send, &send_send);
	if((send_send.SW1!=0x90) || (send_send.SW2!=0x00)) {
		debug("get verify pin fail\n");
		return -ERR_CARD_OP;
	}
	send_send.type    = READER_CONTACTLESS_CPU;
	send_send.CLA     = 0x80;
	send_send.CMD.INS = APDU_GET_BALANCE;
	send_send.PA1.P1  = 0x00;
	send_send.PA2.P2  = 0x01; /* 0x01=ED（电子存折）, 0x02=EP（电子钱包）*/
	send_send.LEN.Lc  = 0; 
	send_send.Le      = 4; /* 指定读取长度 */
	reader_transcive(&send_send, &send_send);
	if((send_send.SW1!=0x90) || (send_send.SW2!=0x00)) {
		debug("get ed balance fail\n");
		return -ERR_CARD_OP;
	}
	info->ed_balance = (send_send.DATA[0]<<24)
			| (send_send.DATA[1]<<16)
			| (send_send.DATA[2]<<8)
			| (send_send.DATA[3]<<0);

	info->card_type = 0x02;
	info->card_id = *(unsigned int *)card_id;

	debug("cpu card slect\n");
	return 0;
}
#endif



